import socket
import pickle
import json
from typing import Dict, Any, List
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import rsa
import numpy as np
import base64
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class CentralServer:
    def __init__(self, fernet_key: bytes, host: str = 'localhost', port: int = 5000):
        self.host = host
        self.port = port
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048
        )
        self.public_key = self.private_key.public_key()
        self.fernet_key = fernet_key
        self.cipher_suite = Fernet(self.fernet_key)
        self.participant_data = []
        
    def start_server(self):
        """启动服务器"""
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.bind((self.host, self.port))
                s.listen()
                logger.info(f"服务器启动在 {self.host}:{self.port}")
                
                while True:
                    conn, addr = s.accept()
                    with conn:
                        logger.info(f"连接来自 {addr}")
                        data = conn.recv(4096)
                        if not data:
                            break
                        try:
                            self.process_participant_data(pickle.loads(data))
                        except Exception as e:
                            logger.error(f"处理数据时出错: {str(e)}")
        except Exception as e:
            logger.error(f"服务器运行出错: {str(e)}")
                    
    def process_participant_data(self, data: Dict[str, bytes]):
        """处理参与者数据"""
        try:
            self.participant_data.append(data)
            logger.info(f"成功处理来自参与者的数据")
        except Exception as e:
            logger.error(f"处理参与者数据时出错: {str(e)}")
        
    def verify_metadata_consistency(self) -> bool:
        """验证元数据一致性"""
        if not self.participant_data:
            logger.warning("没有参与者数据")
            return False
            
        try:
            # 获取第一个参与者的元数据哈希作为基准
            base_hash = self.participant_data[0]['metadata_hash']
            
            # 验证其他参与者的元数据哈希是否一致
            for data in self.participant_data[1:]:
                if data['metadata_hash'] != base_hash:
                    logger.warning("元数据不一致")
                    return False
            return True
        except Exception as e:
            logger.error(f"验证元数据一致性时出错: {str(e)}")
            return False
    
    def aggregate_compliance_results(self) -> Dict[str, float]:
        """聚合合规性结果"""
        if not self.participant_data:
            logger.warning("没有参与者数据")
            return {}
            
        try:
            aggregated_results = {}
            total_participants = len(self.participant_data)
            logger.info(f"开始聚合 {total_participants} 个参与者的合规性结果")
            
            # 解密并聚合所有参与者的合规性结果
            for i, data in enumerate(self.participant_data):
                try:
                    # 检查必要字段是否存在
                    if 'encrypted_compliance' not in data:
                        logger.error(f"参与者 {i+1} 的数据缺少 encrypted_compliance 字段")
                        continue
                        
                    # 解密合规性结果
                    decrypted_compliance = json.loads(
                        self.cipher_suite.decrypt(data['encrypted_compliance'])
                    )
                    logger.info(f"成功解密参与者 {i+1} 的合规性结果")
                    
                    # 验证解密结果格式
                    if not isinstance(decrypted_compliance, dict):
                        logger.error(f"参与者 {i+1} 的合规性结果格式错误")
                        continue
                        
                    # 聚合结果
                    for col, score in decrypted_compliance.items():
                        if not isinstance(score, (int, float)):
                            logger.warning(f"参与者 {i+1} 的字段 {col} 的分数类型错误")
                            continue
                            
                        if col not in aggregated_results:
                            aggregated_results[col] = 0.0
                        aggregated_results[col] += float(score)
                        
                except json.JSONDecodeError as e:
                    logger.error(f"参与者 {i+1} 的合规性结果JSON解析错误: {str(e)}")
                    continue
                except Exception as e:
                    logger.error(f"处理参与者 {i+1} 的数据时出错: {str(e)}")
                    continue
            
            # 计算平均值
            if aggregated_results:
                for col in aggregated_results:
                    aggregated_results[col] /= total_participants
                logger.info("成功计算所有字段的平均合规性分数")
            else:
                logger.warning("没有有效的合规性结果可以聚合")
                
            return aggregated_results
            
        except Exception as e:
            logger.error(f"聚合合规性结果时发生未预期的错误: {str(e)}")
            return {}
    
    def generate_global_report(self) -> Dict[str, Any]:
        """生成全局报告"""
        try:
            metadata_consistent = self.verify_metadata_consistency()
            compliance_results = self.aggregate_compliance_results()
            
            # 计算总体质量分数
            overall_score = 0.0
            if compliance_results:
                scores = list(compliance_results.values())
                if scores:
                    overall_score = float(np.mean(scores))
            
            report = {
                "metadata_consistency": metadata_consistent,
                "compliance_results": compliance_results,
                "total_participants": len(self.participant_data),
                "overall_quality_score": overall_score
            }
            
            return report
        except Exception as e:
            logger.error(f"生成全局报告时出错: {str(e)}")
            return {
                "error": str(e),
                "metadata_consistency": False,
                "compliance_results": {},
                "total_participants": 0,
                "overall_quality_score": 0.0
            }
    
    def sign_report(self, report: Dict[str, Any]) -> str:
        """对报告进行数字签名"""
        try:
            report_str = json.dumps(report, sort_keys=True)
            signature = self.private_key.sign(
                report_str.encode(),
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            return base64.b64encode(signature).decode('utf-8')
        except Exception as e:
            logger.error(f"签名报告时出错: {str(e)}")
            return ""
    
    def encrypt_and_store_report(self, report: Dict[str, Any], 
                               signature: str, 
                               output_path: str):
        """加密并存储报告"""
        try:
            report_data = {
                "report": report,
                "signature": signature
            }
            
            encrypted_data = self.cipher_suite.encrypt(
                json.dumps(report_data).encode()
            )
            
            with open(output_path, 'wb') as f:
                f.write(encrypted_data)
            logger.info(f"报告已成功存储到 {output_path}")
        except Exception as e:
            logger.error(f"存储报告时出错: {str(e)}")
    
    def generate_plain_report(self, report: Dict[str, Any], 
                            signature: str, 
                            output_path: str):
        """生成不加密的报告"""
        try:
            report_data = {
                "report": report,
                "signature": signature,
                "generated_at": datetime.now().isoformat(),
                "report_version": "1.0"
            }
            
            # 格式化JSON输出
            formatted_json = json.dumps(report_data, 
                                     indent=4, 
                                     ensure_ascii=False,
                                     sort_keys=True)
            
            with open(output_path, 'w', encoding='utf-8') as f:
                f.write(formatted_json)
            logger.info(f"不加密报告已成功存储到 {output_path}")
            
            # 打印报告摘要
            self.print_report_summary(report)
        except Exception as e:
            logger.error(f"生成不加密报告时出错: {str(e)}")
    
    def print_report_summary(self, report: Dict[str, Any]):
        """打印报告摘要"""
        print("\n=== 数据质量检查报告摘要 ===")
        print(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"参与方数量: {report['total_participants']}")
        print(f"元数据一致性: {'通过' if report['metadata_consistency'] else '未通过'}")
        print("\n格式合规性结果:")
        for col, score in report['compliance_results'].items():
            print(f"- {col}: {score:.2%}")
        print(f"\n总体质量分数: {report['overall_quality_score']:.2%}")
        print("=" * 30) 